/**
 * \file  antiviral_set.cpp
 * \brief Definition of Antiviral Set implementation class.
 *
 * LAV: Lib Anti Virals
 * <http://lav.googlecode.com/>
 * Copyright (C) 2010 Velez Ezequiel, Peralta Andres,
 *               2013 Boretto Martin, Lenarduzzi Federico,
 *                    Alberione Fernando, Ocampo Emanuel FuDePAN
 *
 * This file is part of the LAV project.
 *
 * Contents:       Cpp file for LAV providing class Antiviral implementation.
 *
 * System:         LAV
 * Language:       C++
 *
 * Author:         Velez Ezequiel, Peralta Andres
 * E-Mail:
 *
 * Author:         Boretto Martin
 * E-Mail:         martinboretto@gmail.com
 *
 * Author:         Lenarduzzi Federico
 * E-Mail:         federicolenarduzzi@gmail.com
 *
 * Author:         Alberione Fernando
 * E-Mail:         falberione037@gmail.com
 *
 * Author:         Ocampo Emanuel
 * E-Mail:         eocampo86@gmail.com
 *
 * LAV is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LAV is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LAV.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "lav/antiviral_set.h"

using namespace std;

namespace lav
{

AntiviralSet::AntiviralSet():
    combinator(antivirals),
    ranker(antivirals),
    mutants(antivirals)
{}


ArvsSet::iterator AntiviralSet::begin()const
{
    return antivirals.begin();
}


ArvsSet::iterator AntiviralSet::end()const
{
    return antivirals.end();
}


size_t AntiviralSet::size() const
{
    return antivirals.size();
}


AVIterator AntiviralSet::begin_AVIterator()const
{
    return AVIterator(antivirals);
}


void AntiviralSet::clone(AntiviralSet& new_avs) const
{
    ArvsSet::iterator it_a = new_avs.antivirals.begin();
    for (ArvsSet::iterator it = begin(); it != end(); ++it)
    {
        ResisBasedAntiviral* aux = new ResisBasedAntiviral(**it);
        new_avs.antivirals.insert(aux);
        ++it_a;
    }
}


void AntiviralSet::to_id_list(AntiviralIdentifierContainer& res_list) const
{
    AntiviralIdentifier id;
    for (ArvsSet::iterator it = begin(); it != end(); ++it)
    {
        (*it)->get_attrib("id", id);
        mili::insert_into(res_list, id);
    }
}


void AntiviralSet::remove(const AntiviralIdentifierContainer& id_to_rem)
{
    for (AntiviralIdentifierContainer::const_iterator it_ids = id_to_rem.begin(); it_ids != id_to_rem.end();
            ++it_ids)
        remove_id(*it_ids);
}


void AntiviralSet::remove_id(AntiviralIdentifier id_to_rem)
{
    ArvsSet::iterator it_av = find(id_to_rem);
    if (it_av != end())
        antivirals.erase(*it_av);
}


ArvsSet::iterator AntiviralSet::find(AntiviralIdentifier id_target) const
{
    ArvsSet::iterator it_av = begin();
    bool found = false;
    AntiviralIdentifier id;
    while (it_av != end() and !found)
    {
        (*it_av)->get_attrib("id", id);
        found = (id == id_target);
        if (!found)
            ++it_av;
    }
    return it_av;
}


void AntiviralSet::remove(ResisBasedAntiviral* antiviral)
{
    antivirals.erase(antiviral);
}


void AntiviralSet::select(const AntiviralIdentifierContainer& ids, AntiviralSet& selection) const
{
    ArvsSet::const_iterator it_av;
    for (it_av = antivirals.begin(); it_av != antivirals.end(); ++it_av)
    {
        AntiviralIdentifier id;
        (*it_av)->get_attrib("id", id);
        AntiviralIdentifierContainer::const_iterator it_list;
        for (it_list = ids.begin(); it_list != ids.end(); ++it_list)
        {
            if (id == (*it_list))
                selection.add_antiviral(**it_av);
        }
    }
}


void AntiviralSet::add_antiviral(ResisBasedAntiviral& antiviral)
{
    mili::insert_into(antivirals, &antiviral);
}

// -----------------------
// Private methods section
// -----------------------

void AntiviralSet::observe_mutants(const biopp::PseudoNucSequence& sequence, MutantDist& mutant_list)
{
    AVIterator it(antivirals);
    while (!it.end())
    {
        (*it)->mutate_sequence(sequence, mutant_list);
        ++it;
    }
}


void AntiviralSet::combine_set(ResisBasedAntiviral& combined)
{
    ResisBasedAntiviral aux("Aux", 0, tComb, cComb);

    AVIterator it(antivirals);

    while (!it.end())
    {
        (*it)->combine_with(combined);
        ++it;
    }
}


void AntiviralSet::get_info(AntiviralsNames& out) const
{
    AntiviralsNames name;
    for (AVIterator it(antivirals); !it.end(); ++it)
    {
        (*it)->get_attrib("name", name);
        out += name;
        out += " + ";
    }
}


void AntiviralSet::split_antivirals_by_type(ResisBasedAntiviralContainer& nrti, ResisBasedAntiviralContainer& nnrti,
        ResisBasedAntiviralContainer& pi) const
{
    AntiviralClass avclass;
    ArvsSet::const_iterator it = this->antivirals.begin();
    while (it != this->antivirals.end())
    {
        (*it)->get_attrib("class", avclass);
        if (avclass == "cNRTI")
            mili::insert_into(nrti, **it);
        else if (avclass == "cNNRTI")
            mili::insert_into(nnrti, **it);
        else if (avclass == "cPI")
            mili::insert_into(pi, **it);

        ++it;
    }
}

}
